﻿
namespace ZDS.Test

open System

open NUnit.Framework
open FsUnit

open ZDS
open TestUtility

[<TestFixture>]
type TestBiDirectLinkList()=

    [<Test>]
    member this.TestAppend()=
        let x = new ZBiDirectLinkList<int>()

        for index = 1 to 3 do
            x.Append index

        x |> should equal [1;2;3]

    [<Test>]
    member this.TestReverseIterate() =
        let x = new ZBiDirectLinkList<int>()

        for index = 1 to 3 do
            x.Append <| index*index

        x.ReverseEnumerable
        |> should equal [9;4;1]

    [<Test>]
    member this.TestGetSet() =
        let x = new ZBiDirectLinkList<int>()

        for index = 1 to 3 do
            x.Append index

        x.[0] |> should equal 1
        x.[2] |> should equal 3

        (fun() -> x.[3] |> ignore)
        |> getErrorCode
        |> should equal ErrorCode.OutofRange

        x.Append 100
        x.[3] <- 66
        x.ReverseEnumerable
        |> should equal [66;3;2;1]

    [<Test>]
    member this.TestInsertMiddle() =
        let x = new ZBiDirectLinkList<int>()

        for index = 1 to 3 do
            x.Append <| index*index

        x.Insert 1 100
        x.Insert 1 200

        x.[1] |> should equal 200
        x |> should equal [1;200;100;4;9]
        x.Size |> should equal 5

        x.Insert (x.Size - 1) 88
        x |> should equal [1;200;100;4;88;9]
        x.ReverseEnumerable |> should equal ([1;200;100;4;88;9] |> List.rev)

    [<Test>]
    member this.TestInsertHead() =
        let x = new ZBiDirectLinkList<int>()
        
        let original = [100;88;99;66]
        original |> Seq.iter (x.Insert 0)
        
        x |> should equal (original |> List.rev)   
        x.Size |> should equal 4

    [<Test>]
    member this.TestInsertRear() =
        let y = new ZBiDirectLinkList<int>()

        for index = 1 to 3 do
            y.Insert y.Size index

        y |> should equal [1;2;3]
        y.ReverseEnumerable |> should equal [3;2;1]
        y.Size |> should equal 3

        (fun() -> y.Insert (y.Size+1) -1 )
        |> TestUtility.getErrorCode
        |> should equal ErrorCode.OutofRange

        y.Append 9
        y |> should equal [1;2;3;9] // to verify that Rear is correctly set
        y.ReverseEnumerable |> should equal [9;3;2;1]

    [<Test>]
    member this.TestRemoveMiddle() =
        let x = new ZBiDirectLinkList<int>()

        for index = 1 to 4 do
            x.Append index

        x.Remove 1 |> should equal 2
        x |> should equal [1;3;4]
        x.ReverseEnumerable |> should equal [4;3;1]
        
        x.Remove 1 |> should equal 3
        x.Remove 1 |> should equal 4

        (fun() -> x.Remove 1 |> ignore)
        |> TestUtility.getErrorCode
        |> should equal ErrorCode.OutofRange   

    [<Test>]
    member this.TestRemoveHead() =
        
        let x = new ZBiDirectLinkList<int>()

        (fun () -> x.Remove 0 |> ignore)
        |> TestUtility.getErrorCode
        |> should equal ErrorCode.OutofRange

        let original = [99;6;88;]
        original |> Seq.iter x.Append

        seq {
            for index = 1 to x.Size do
                yield (x.Remove 0)
        }
        |> should equal original

        x.Size |> should equal 0

    [<Test>]
    member this.TestRemoveRear() =
        let x = new ZBiDirectLinkList<int>()

        let original = [99;6;88;]
        original |> Seq.iter x.Append

        seq {
            for index = 1 to x.Size do
                yield (x.Remove (x.Size-1))
        }
        |> should equal (original |> List.rev)
        x.Size |> should equal 0

        x.Append 1234
        x.Insert 0 567
        x |> should equal [567;1234;]
        x.ReverseEnumerable |> should equal [1234;567]

    [<Test>]
    member this.TestMiscellaneous() =
        let x = new ZBiDirectLinkList<int>()

        for index = 1 to 4 do
            x.Append index

        x.Insert 0 5
        x |> should equal [5;1;2;3;4]

        x.Remove 3 |> should equal 3
        x.ReverseEnumerable |> should equal [4;2;1;5]

        x.Remove (x.Size - 1) |> ignore
        x.Append 100
        x.ReverseEnumerable |> should equal [100;2;1;5]
        
